package top.fullj.http;

import com.google.common.base.Preconditions;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import okhttp3.ConnectionSpec;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Converter;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * @author bruce.wu
 * @since 2021/6/24 13:59
 */
@SuppressWarnings({"WeakerAccess", "unused"})
public abstract class RestClient {

    protected <T> T createService(Class<T> service) {
        Retrofit.Builder builder = new Retrofit.Builder();
        builder .addConverterFactory(createConverterFactory())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(resolveBaseUrl(getBaseUrl()))
                .client(createHttpClient());
        return builder.build().create(service);
    }

    private OkHttpClient createHttpClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectionSpecs(Collections.singletonList(getConnectionSpec()))
                .connectTimeout(getConnectTimeoutInMs(), TimeUnit.MILLISECONDS)
                .readTimeout(getReadTimeoutInMs(), TimeUnit.MILLISECONDS);
        customize(builder);
        return builder.build();
    }

    protected void customize(OkHttpClient.Builder builder) {
        builder.addNetworkInterceptor(createLoggingInterceptor());
    }

    protected abstract String getBaseUrl();

    protected ConnectionSpec getConnectionSpec() {
        return ConnectionSpec.RESTRICTED_TLS;
    }

    protected long getConnectTimeoutInMs() {
        return 5 * 1000;
    }

    protected long getReadTimeoutInMs() {
        return 60 * 1000;
    }

    private Interceptor createLoggingInterceptor() {
        return new HttpLoggingInterceptor(getLogger())
                .setLevel(getLoggerLevel());
    }

    protected HttpLoggingInterceptor.Logger getLogger() {
        return new HttpLogger();
    }

    protected HttpLoggingInterceptor.Level getLoggerLevel() {
        return HttpLoggingInterceptor.Level.BODY;
    }

    protected String resolveBaseUrl(String url) {
        Preconditions.checkNotNull(url);
        return url.endsWith("/") ? url : (url + "/");
    }

    protected Converter.Factory createConverterFactory() {
        Gson gson = new GsonBuilder().create();
        return GsonConverterFactory.create(gson);
    }

}
